package com.hmdp.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.hmdp.dto.UserDTO;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.TimeUnit;


// 拦截 所有的 请求 并刷新 token
public class RefreshTokenInterceptor implements HandlerInterceptor {

    private StringRedisTemplate stringRedisTemplate;

    public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 登录状态 验证  所以 首先 登录 之后 会将 用户 信息 放在session 里 所以 要 先 获取 session
        //

//        HttpSession session = request.getSession();
        String token = request.getHeader("authorization");  // 获取 前端的 token

//        Object user = session.getAttribute("user");  // 现在 获取到的 是 UserDto

        if (StrUtil.isBlank(token)) {  // 空白的 直接 放行 因为 还没有登录 所以 下面的 校验 就 不需要了
            return true;   // 这个 因为 第一次 登录的 时候 是没有 后面 这个些的 所以 直接放行  还有 发送 验证码的 时候 都没有,  这个 有 问题 没有 token 直接 放行了 如果 不这样的 话 可能
        }

        String key = RedisConstants.LOGIN_USER_KEY+token;  // redis 里面的user的保存的key

        // 获取 hash 的 所有的 key 和 value
        Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(key);  // 这个 获取 不到  用户 信息 用户 信息 保存在 redis 里面 有失效 机制  这种 时候 不能 放行把

        // 然后 将 map 转换为 一个 对象
        // 要想 从redis 李米娜
        /// 都放行 后面 没有 user 就会 拦截 请求的
        if(entries.isEmpty()){   // 没有 查询到 用户 信息 就认为 本次会话 没有 登录 所以 就 会 被 拦截(拦截 还是 放行 是 通过 这个 函数的 返回值 来 体现的)
           return true;   // 发送了 验证码 但是 没有 登录 页 要 放行 ，  要确保 每一步的 前提 条件 是满足的
        }


        // 有 信息 之后 才 转化  不然 直接报错
        UserDTO user = BeanUtil.fillBeanWithMap(entries, new UserDTO(), false);

        // 用户 存在(即 本次 会话 用户 已经 登录 了  因为 只有 登录了之后 才会有用户信息 )  为什么 要 存到 Threadlocal

        UserHolder.saveUser(user);  // 存放 到 Threadlocal
        // 访问了 这个 key 所以 是一个 活跃的 key 重置 过期 时间
        stringRedisTemplate.expire(key,RedisConstants.LOGIN_USER_TTL, TimeUnit.SECONDS);  // 重置 过期时间
        return true; // 这个 方法 返回 true 就可以 放行了

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 移除用户
        UserHolder.removeUser();  // 访问 之后 溢出
    }
}
